#!/usr/bin/env python3
"""
RedFire 数据库系统统一部署工具
整合构建、部署、监控功能
"""

import os
import sys
import subprocess
import argparse
import yaml
from pathlib import Path
from typing import Dict, List, Optional
from datetime import datetime

# 添加工具目录到Python路径
sys.path.append(str(Path(__file__).parent))

try:
    from environment_manager import EnvironmentManager
    from config_validator import ConfigValidator
except ImportError:
    print("警告: 无法导入环境管理和配置验证工具")
    EnvironmentManager = None
    ConfigValidator = None


class DeployManager:
    """部署管理器"""
    
    def __init__(self, project_root: str = None):
        self.project_root = Path(project_root or os.getcwd())
        self.databases_dir = self.project_root / "databases"
        self.compose_file = self.databases_dir / "docker-compose.yml"
        self.env_file = self.databases_dir / ".env"
        
        # 检查必要文件
        if not self.compose_file.exists():
            raise FileNotFoundError(f"Docker Compose文件不存在: {self.compose_file}")
    
    def check_prerequisites(self) -> bool:
        """检查前置条件"""
        print("🔍 检查前置条件...")
        
        # 检查Docker
        try:
            result = subprocess.run(['docker', '--version'], 
                                  capture_output=True, text=True, check=True)
            print(f"✅ Docker: {result.stdout.strip()}")
        except (subprocess.CalledProcessError, FileNotFoundError):
            print("❌ Docker未安装或不可用")
            return False
        
        # 检查Docker Compose
        try:
            result = subprocess.run(['docker', 'compose', 'version'], 
                                  capture_output=True, text=True, check=True)
            print(f"✅ Docker Compose: {result.stdout.strip()}")
        except (subprocess.CalledProcessError, FileNotFoundError):
            print("❌ Docker Compose未安装或不可用")
            return False
        
        # 检查环境变量
        if EnvironmentManager:
            env_manager = EnvironmentManager()
            validation_result = env_manager.validate_environment()
            
            if validation_result['is_valid']:
                print("✅ 环境变量配置完整")
            else:
                print("⚠️ 环境变量配置不完整")
                if validation_result['missing_vars']:
                    print(f"   缺少: {', '.join(validation_result['missing_vars'])}")
                for warning in validation_result['warnings']:
                    print(f"   警告: {warning}")
        
        return True
    
    def build_images(self, force: bool = False) -> bool:
        """构建Docker镜像"""
        print("🔨 构建Docker镜像...")
        
        cmd = ['docker', 'compose', 'build']
        if force:
            cmd.append('--no-cache')
        
        try:
            subprocess.run(cmd, cwd=self.databases_dir, check=True)
            print("✅ 镜像构建完成")
            return True
        except subprocess.CalledProcessError as e:
            print(f"❌ 镜像构建失败: {e}")
            return False
    
    def start_services(self, services: List[str] = None) -> bool:
        """启动服务"""
        print("🚀 启动服务...")
        
        cmd = ['docker', 'compose', 'up', '-d']
        if services:
            cmd.extend(services)
        
        try:
            subprocess.run(cmd, cwd=self.databases_dir, check=True)
            print("✅ 服务启动完成")
            self._show_access_urls()
            return True
        except subprocess.CalledProcessError as e:
            print(f"❌ 服务启动失败: {e}")
            return False
    
    def stop_services(self, services: List[str] = None) -> bool:
        """停止服务"""
        print("🛑 停止服务...")
        
        cmd = ['docker', 'compose', 'down']
        if services:
            cmd.extend(services)
        
        try:
            subprocess.run(cmd, cwd=self.databases_dir, check=True)
            print("✅ 服务已停止")
            return True
        except subprocess.CalledProcessError as e:
            print(f"❌ 服务停止失败: {e}")
            return False
    
    def show_status(self) -> bool:
        """显示服务状态"""
        print("📊 服务状态:")
        
        try:
            subprocess.run(['docker', 'compose', 'ps'], 
                         cwd=self.databases_dir, check=True)
            return True
        except subprocess.CalledProcessError as e:
            print(f"❌ 获取状态失败: {e}")
            return False
    
    def show_logs(self, service: str = None, follow: bool = False, tail: int = 50) -> bool:
        """显示服务日志"""
        print(f"📋 服务日志 {'(实时)' if follow else ''}:")
        
        cmd = ['docker', 'compose', 'logs', f'--tail={tail}']
        if follow:
            cmd.append('-f')
        if service:
            cmd.append(service)
        
        try:
            subprocess.run(cmd, cwd=self.databases_dir, check=True)
            return True
        except subprocess.CalledProcessError as e:
            print(f"❌ 获取日志失败: {e}")
            return False
        except KeyboardInterrupt:
            print("\n📋 日志查看已停止")
            return True
    
    def clean_environment(self, volumes: bool = False) -> bool:
        """清理环境"""
        print("🧹 清理环境...")
        
        # 停止所有服务
        cmd = ['docker', 'compose', 'down']
        if volumes:
            cmd.extend(['-v', '--remove-orphans'])
        
        try:
            subprocess.run(cmd, cwd=self.databases_dir, check=True)
            
            # 清理未使用的Docker资源
            subprocess.run(['docker', 'system', 'prune', '-f'], check=True)
            
            print("✅ 环境清理完成")
            return True
        except subprocess.CalledProcessError as e:
            print(f"❌ 环境清理失败: {e}")
            return False
    
    def validate_configs(self) -> bool:
        """验证配置文件"""
        print("🔍 验证配置文件...")
        
        if not ConfigValidator:
            print("⚠️ 配置验证器不可用")
            return True
        
        validator = ConfigValidator()
        config_files = [
            self.databases_dir / "env.example",
            self.databases_dir / "docker-compose.yml"
        ]
        
        all_valid = True
        for config_file in config_files:
            if config_file.exists():
                try:
                    result = validator.validate_config_file(str(config_file))
                    status = "✅" if result.is_valid else "❌"
                    print(f"{status} {config_file.name}: {result.score:.1f}/100")
                    
                    if result.errors:
                        for error in result.errors[:3]:  # 只显示前3个错误
                            print(f"   错误: {error}")
                    
                    if not result.is_valid:
                        all_valid = False
                        
                except Exception as e:
                    print(f"⚠️ 验证 {config_file.name} 失败: {e}")
        
        return all_valid
    
    def _show_access_urls(self):
        """显示访问地址"""
        print("\n🌐 服务访问地址:")
        print("  📊 phpMyAdmin:      http://localhost:8080")
        print("  🐘 pgAdmin:         http://localhost:8081")
        print("  🔴 Redis Commander: http://localhost:8082")
        print("  📈 Grafana:         http://localhost:3000")
        print("  🔍 Prometheus:      http://localhost:9090")
    
    def backup_data(self, backup_dir: str = None) -> bool:
        """备份数据"""
        if not backup_dir:
            backup_dir = f"backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        
        backup_path = self.databases_dir / backup_dir
        backup_path.mkdir(exist_ok=True)
        
        print(f"💾 备份数据到: {backup_path}")
        
        # 这里可以添加具体的备份逻辑
        # 例如：导出数据库、备份配置文件等
        
        return True


def main():
    """命令行入口"""
    parser = argparse.ArgumentParser(description='RedFire 数据库系统部署工具')
    parser.add_argument('action', choices=[
        'check', 'build', 'up', 'down', 'restart', 
        'status', 'logs', 'clean', 'validate', 'backup'
    ], help='执行的操作')
    
    parser.add_argument('--service', '-s', help='指定服务名称')
    parser.add_argument('--force', '-f', action='store_true', help='强制执行')
    parser.add_argument('--follow', action='store_true', help='实时跟踪日志')
    parser.add_argument('--volumes', '-v', action='store_true', help='清理时包含数据卷')
    parser.add_argument('--tail', type=int, default=50, help='日志行数')
    
    args = parser.parse_args()
    
    try:
        # 查找项目根目录
        current_dir = Path.cwd()
        project_root = current_dir
        
        # 向上查找包含databases目录的父目录
        while project_root.parent != project_root:
            if (project_root / "databases").exists():
                break
            project_root = project_root.parent
        else:
            # 如果当前就在databases目录中
            if current_dir.name == "databases":
                project_root = current_dir.parent
            else:
                project_root = current_dir
        
        deploy_manager = DeployManager(str(project_root))
        
        # 执行相应操作
        if args.action == 'check':
            success = deploy_manager.check_prerequisites()
        elif args.action == 'build':
            success = (deploy_manager.check_prerequisites() and 
                      deploy_manager.build_images(force=args.force))
        elif args.action == 'up':
            services = [args.service] if args.service else None
            success = (deploy_manager.check_prerequisites() and 
                      deploy_manager.start_services(services))
        elif args.action == 'down':
            services = [args.service] if args.service else None
            success = deploy_manager.stop_services(services)
        elif args.action == 'restart':
            services = [args.service] if args.service else None
            success = (deploy_manager.stop_services(services) and 
                      deploy_manager.start_services(services))
        elif args.action == 'status':
            success = deploy_manager.show_status()
        elif args.action == 'logs':
            success = deploy_manager.show_logs(
                service=args.service, 
                follow=args.follow, 
                tail=args.tail
            )
        elif args.action == 'clean':
            success = deploy_manager.clean_environment(volumes=args.volumes)
        elif args.action == 'validate':
            success = deploy_manager.validate_configs()
        elif args.action == 'backup':
            success = deploy_manager.backup_data()
        else:
            parser.print_help()
            success = False
        
        sys.exit(0 if success else 1)
        
    except KeyboardInterrupt:
        print("\n操作已取消")
        sys.exit(1)
    except Exception as e:
        print(f"❌ 操作失败: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
